#include "String.h"

template<class T>
class StringArray
{
private:
	T** data;
	int l;
	int al;
	String<T> ts;
	
	#define LD sizeof(T*)
	bool Resize(int ns, bool a)
	{
		if (a) ns+= al;
		if (ns>al)
		{
			al = ns;
			T** nd = new T*[al+1];
			memset(nd,0,(al+1)*LD);
			
			if (!nd) return false;
			
			memcpy(nd,data,(l+1)*LD);
			delete [] data;
			data = nd;
		}
		else
		{
			for(int i = al;i>=ns;i--)
			{
				free(data[i]);
				data[i] = NULL;
			}
		}
		return true;
	}

	static int StrLen(const T* s)
	{
		int i = 0;
		if (s)
		{
			while(*s++) i++;
		}
		return i;
	}

	static bool StrCmp(const T* d, const T* s)
	{
		if (!d && !s ) return true;
		if (!d || !s) return false;
		while(1)
		{
			if (*d && *s && *d!=*s) return false;
			d++; s++;
		}
		if (*d || *s) return false;
		return true;
	}

public:

	StringArray() 
	{ 
		al = 10; 
		l = -1; 
		data = (T**)malloc((al+1)*LD); 
		memset(data,0,(al+1)*LD); 
	}

	~StringArray()
	{
		RemoveAll();
		free(data);
	}

	bool FindEntry(T* s, int& i) const
	{
		for(i=0; i<=l; i++)
		{
			if (StrCmp(data[i],s)==0) return true;
		}
		return false;	
	}

	int FindEntry(T* s) const
	{
		int i = -1;
		if (FindEntry(s,i))
		{
			return i;
		}
		return -1;
	}

	bool SetAt(int idx, T* s)
	{
		if (idx<=l)
		{
			T* ns = (T*)malloc((StrLen(s)+1)*sizeof(T));
			if (!ns) return false;

			MemCpy(ns,s,StrLen(s)+1);
			data[idx] = ns;
		}
		else
			Add(s);

		return true;
	}

	bool Insert(int idx,T* s)
	{
		if (l+1>=al)
		{
			Resize(10, true);
		}
		for(int i=l; i>=idx; i--)
			data[i+1] = data[i];

		l++;
		return SetAt(idx,s);
	}

	bool Add(T* s)
	{
		if (l+1>=al && !Resize(10,true)) return false;
		
		T * ns = new T[StrLen(s)+1];
		memset(ns,0,(StrLen(s)+1)*sizeof(T));
		if (!ns) return false;

		memcpy(ns,s,(StrLen(s)+1)*LD);
		data[++l] = ns;
		return true;
	}

	bool Append(const StringArray& s)
	{
		for(int i=0;i<=s.l;i++)
		{
			if (!Add(s.data[i])) return false;
		}
		return true;
	}

	bool Remove(int idx)
	{
		if (idx>l) return false;
		free(data[idx]);
		memcpy(&data[idx],&data[idx+1],(l-idx+1)*LD);
		l--;
		return true;
	}

	bool Remove(T* s)
	{
		int i;
		bool rc = false;
		if (FindEntry(s,i))
		{
			if (Remove(i))
			{
				rc = true;
				Remove(s);
			}
		}
		return rc;
	}


	bool RemoveAll()
	{
		while(l>-1)
		{
			delete [] data[l];
			data[l--] = NULL;
		}
		return true;
	}


	String<T>& GetAt(int idx)
	{
		if (idx<=l)	
			ts = data[idx];
		else
			ts = "";
		return ts;
	}

	T* &operator[](int idx)
	{
		return data[idx];
	}

};
